package com.futong.cloud.action;

import cn.hutool.core.util.ClassUtil;
import com.futong.cloud.dao.ActionMapper;
import com.futong.cloud.utils.ScriptUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import javax.script.ScriptEngine;
import javax.script.ScriptException;
import java.util.*;
import java.util.stream.Collectors;

import static cn.hutool.core.util.ClassUtil.getClassName;

/**
 * @program: futong-cm
 * @description:
 * @author: lipengpeng
 * @create: 2021/10/12 15:29
 */
@Slf4j
public class ActionRegister  {
    private static Map<String, ActionConsumer> functions=new HashMap<>();
    private static Map<String, ActionModel> actions=new HashMap<>();
    public static Map<String, ActionModel> getActions() {
        return actions;
    }
    public static void refresh() {
        List<ActionModel> infos = ActionMapper.Mappers.action.listAction();
        Assert.notEmpty(infos,"query database action_info is empty!");
        loadFunctions();
        actions=loadActions(infos);
        ScriptUtils.cache=loadScript(infos);
    }
    private static Map<String, ActionModel> loadActions(List<ActionModel> infos){
        return infos.stream().filter(t->{
            if(CollectionUtils.isNotEmpty(t.getFunctions()))return true;
            log.error("fail load action:\"{}\" function is empty!", t.getCmpAction());
            return false;
        }).map(t->{
            t.getFunctions().stream().forEach(s -> {
                if (!functions.containsKey(s.getMethod())){
                    log.error("fail load action:\"{}\" function:\"{}\" not exists!", t.getCmpAction(), s);
                }else {
                    s.setConsumer(functions.get(s.getMethod()));
                }
            });
            log.info("success load action:\"{}\"",t.getCmpAction());
            return new AbstractMap.SimpleEntry<>(t.getCmpAction()+"_"+t.getCloudType()+"_"+t.getVersion(),t);
        }).collect(Collectors.toMap(t->t.getKey(),t->t.getValue()));
    };
    private static void loadFunctions(){
        functions.clear();
        Set<Class<?>> classes = ClassUtil.scanPackage("com.futong.cloud.function");
        classes.stream().forEach(t->{
            String name= getClassName(t,true);
            Arrays.stream(ClassUtil.getDeclaredFields(t))
                    .filter(f -> f.getType().equals(ActionConsumer.class))
                    .forEach(f->{
                        String key=name+"."+f.getName();
                        try {
                            ActionConsumer value=(ActionConsumer)f.get(t);
                            log.info("success load function:"+key);
                            functions.put(key,value);
                        } catch (IllegalAccessException e) {
                            log.error("fail load function:"+key+" error:{}",e);
                        }
                    });
        });
    }
    private static ScriptEngine loadScript(List<ActionModel> infos){
        ScriptEngine se = ScriptUtils.generate();
        infos.stream().flatMap(t->t.getFileds().stream()).distinct().forEach(
            t->{
                String script="var _"+t.getId()+" = "+t.getValid();
                try {
                    ScriptUtils.exec(se,script);
                    log.info("success load script filed:{} script:{}",t.getFiled(),script);
                } catch (ScriptException e) {
                    log.error("fail load script filed{}:error:{}",t,e);
                }
            }
        );
        return se;
    }
}
